home *** CD-ROM | disk | FTP | other *** search
/ Clickx 115 / Clickx 115.iso / software / tools / windows / tails-i386-0.16.iso / live / filesystem.squashfs / usr / lib / python2.6 / bdb.py < prev    next >
Encoding:
Python Source  |  2010-12-26  |  20.1 KB  |  618 lines

  1. """Debugger basics"""
  2.  
  3. import sys
  4. import os
  5. import types
  6.  
  7. __all__ = ["BdbQuit","Bdb","Breakpoint"]
  8.  
  9. class BdbQuit(Exception):
  10.     """Exception to give up completely"""
  11.  
  12.  
  13. class Bdb:
  14.  
  15.     """Generic Python debugger base class.
  16.  
  17.     This class takes care of details of the trace facility;
  18.     a derived class should implement user interaction.
  19.     The standard debugger class (pdb.Pdb) is an example.
  20.     """
  21.  
  22.     def __init__(self):
  23.         self.breaks = {}
  24.         self.fncache = {}
  25.  
  26.     def canonic(self, filename):
  27.         if filename == "<" + filename[1:-1] + ">":
  28.             return filename
  29.         canonic = self.fncache.get(filename)
  30.         if not canonic:
  31.             canonic = os.path.abspath(filename)
  32.             canonic = os.path.normcase(canonic)
  33.             self.fncache[filename] = canonic
  34.         return canonic
  35.  
  36.     def reset(self):
  37.         import linecache
  38.         linecache.checkcache()
  39.         self.botframe = None
  40.         self._set_stopinfo(None, None)
  41.  
  42.     def trace_dispatch(self, frame, event, arg):
  43.         if self.quitting:
  44.             return # None
  45.         if event == 'line':
  46.             return self.dispatch_line(frame)
  47.         if event == 'call':
  48.             return self.dispatch_call(frame, arg)
  49.         if event == 'return':
  50.             return self.dispatch_return(frame, arg)
  51.         if event == 'exception':
  52.             return self.dispatch_exception(frame, arg)
  53.         if event == 'c_call':
  54.             return self.trace_dispatch
  55.         if event == 'c_exception':
  56.             return self.trace_dispatch
  57.         if event == 'c_return':
  58.             return self.trace_dispatch
  59.         print 'bdb.Bdb.dispatch: unknown debugging event:', repr(event)
  60.         return self.trace_dispatch
  61.  
  62.     def dispatch_line(self, frame):
  63.         if self.stop_here(frame) or self.break_here(frame):
  64.             self.user_line(frame)
  65.             if self.quitting: raise BdbQuit
  66.         return self.trace_dispatch
  67.  
  68.     def dispatch_call(self, frame, arg):
  69.         # XXX 'arg' is no longer used
  70.         if self.botframe is None:
  71.             # First call of dispatch since reset()
  72.             self.botframe = frame.f_back # (CT) Note that this may also be None!
  73.             return self.trace_dispatch
  74.         if not (self.stop_here(frame) or self.break_anywhere(frame)):
  75.             # No need to trace this function
  76.             return # None
  77.         self.user_call(frame, arg)
  78.         if self.quitting: raise BdbQuit
  79.         return self.trace_dispatch
  80.  
  81.     def dispatch_return(self, frame, arg):
  82.         if self.stop_here(frame) or frame == self.returnframe:
  83.             self.user_return(frame, arg)
  84.             if self.quitting: raise BdbQuit
  85.         return self.trace_dispatch
  86.  
  87.     def dispatch_exception(self, frame, arg):
  88.         if self.stop_here(frame):
  89.             self.user_exception(frame, arg)
  90.             if self.quitting: raise BdbQuit
  91.         return self.trace_dispatch
  92.  
  93.     # Normally derived classes don't override the following
  94.     # methods, but they may if they want to redefine the
  95.     # definition of stopping and breakpoints.
  96.  
  97.     def stop_here(self, frame):
  98.         # (CT) stopframe may now also be None, see dispatch_call.
  99.         # (CT) the former test for None is therefore removed from here.
  100.         if frame is self.stopframe:
  101.             if self.stoplineno == -1:
  102.                 return False
  103.             return frame.f_lineno >= self.stoplineno
  104.         while frame is not None and frame is not self.stopframe:
  105.             if frame is self.botframe:
  106.                 return True
  107.             frame = frame.f_back
  108.         return False
  109.  
  110.     def break_here(self, frame):
  111.         filename = self.canonic(frame.f_code.co_filename)
  112.         if not filename in self.breaks:
  113.             return False
  114.         lineno = frame.f_lineno
  115.         if not lineno in self.breaks[filename]:
  116.             # The line itself has no breakpoint, but maybe the line is the
  117.             # first line of a function with breakpoint set by function name.
  118.             lineno = frame.f_code.co_firstlineno
  119.             if not lineno in self.breaks[filename]:
  120.                 return False
  121.  
  122.         # flag says ok to delete temp. bp
  123.         (bp, flag) = effective(filename, lineno, frame)
  124.         if bp:
  125.             self.currentbp = bp.number
  126.             if (flag and bp.temporary):
  127.                 self.do_clear(str(bp.number))
  128.             return True
  129.         else:
  130.             return False
  131.  
  132.     def do_clear(self, arg):
  133.         raise NotImplementedError, "subclass of bdb must implement do_clear()"
  134.  
  135.     def break_anywhere(self, frame):
  136.         return self.canonic(frame.f_code.co_filename) in self.breaks
  137.  
  138.     # Derived classes should override the user_* methods
  139.     # to gain control.
  140.  
  141.     def user_call(self, frame, argument_list):
  142.         """This method is called when there is the remote possibility
  143.         that we ever need to stop in this function."""
  144.         pass
  145.  
  146.     def user_line(self, frame):
  147.         """This method is called when we stop or break at this line."""
  148.         pass
  149.  
  150.     def user_return(self, frame, return_value):
  151.         """This method is called when a return trap is set here."""
  152.         pass
  153.  
  154.     def user_exception(self, frame, exc_info):
  155.         exc_type, exc_value, exc_traceback = exc_info
  156.         """This method is called if an exception occurs,
  157.         but only if we are to stop at or just below this level."""
  158.         pass
  159.  
  160.     def _set_stopinfo(self, stopframe, returnframe, stoplineno=0):
  161.         self.stopframe = stopframe
  162.         self.returnframe = returnframe
  163.         self.quitting = 0
  164.         # stoplineno >= 0 means: stop at line >= the stoplineno
  165.         # stoplineno -1 means: don't stop at all
  166.         self.stoplineno = stoplineno
  167.  
  168.     # Derived classes and clients can call the following methods
  169.     # to affect the stepping state.
  170.  
  171.     def set_until(self, frame): #the name "until" is borrowed from gdb
  172.         """Stop when the line with the line no greater than the current one is
  173.         reached or when returning from current frame"""
  174.         self._set_stopinfo(frame, frame, frame.f_lineno+1)
  175.  
  176.     def set_step(self):
  177.         """Stop after one line of code."""
  178.         self._set_stopinfo(None, None)
  179.  
  180.     def set_next(self, frame):
  181.         """Stop on the next line in or below the given frame."""
  182.         self._set_stopinfo(frame, None)
  183.  
  184.     def set_return(self, frame):
  185.         """Stop when returning from the given frame."""
  186.         self._set_stopinfo(frame.f_back, frame)
  187.  
  188.     def set_trace(self, frame=None):
  189.         """Start debugging from `frame`.
  190.  
  191.         If frame is not specified, debugging starts from caller's frame.
  192.         """
  193.         if frame is None:
  194.             frame = sys._getframe().f_back
  195.         self.reset()
  196.         while frame:
  197.             frame.f_trace = self.trace_dispatch
  198.             self.botframe = frame
  199.             frame = frame.f_back
  200.         self.set_step()
  201.         sys.settrace(self.trace_dispatch)
  202.  
  203.     def set_continue(self):
  204.         # Don't stop except at breakpoints or when finished
  205.         self._set_stopinfo(self.botframe, None, -1)
  206.         if not self.breaks:
  207.             # no breakpoints; run without debugger overhead
  208.             sys.settrace(None)
  209.             frame = sys._getframe().f_back
  210.             while frame and frame is not self.botframe:
  211.                 del frame.f_trace
  212.                 frame = frame.f_back
  213.  
  214.     def set_quit(self):
  215.         self.stopframe = self.botframe
  216.         self.returnframe = None
  217.         self.quitting = 1
  218.         sys.settrace(None)
  219.  
  220.     # Derived classes and clients can call the following methods
  221.     # to manipulate breakpoints.  These methods return an
  222.     # error message is something went wrong, None if all is well.
  223.     # Set_break prints out the breakpoint line and file:lineno.
  224.     # Call self.get_*break*() to see the breakpoints or better
  225.     # for bp in Breakpoint.bpbynumber: if bp: bp.bpprint().
  226.  
  227.     def set_break(self, filename, lineno, temporary=0, cond = None,
  228.                   funcname=None):
  229.         filename = self.canonic(filename)
  230.         import linecache # Import as late as possible
  231.         line = linecache.getline(filename, lineno)
  232.         if not line:
  233.             return 'Line %s:%d does not exist' % (filename,
  234.                                    lineno)
  235.         if not filename in self.breaks:
  236.             self.breaks[filename] = []
  237.         list = self.breaks[filename]
  238.         if not lineno in list:
  239.             list.append(lineno)
  240.         bp = Breakpoint(filename, lineno, temporary, cond, funcname)
  241.  
  242.     def clear_break(self, filename, lineno):
  243.         filename = self.canonic(filename)
  244.         if not filename in self.breaks:
  245.             return 'There are no breakpoints in %s' % filename
  246.         if lineno not in self.breaks[filename]:
  247.             return 'There is no breakpoint at %s:%d' % (filename,
  248.                                     lineno)
  249.         # If there's only one bp in the list for that file,line
  250.         # pair, then remove the breaks entry
  251.         for bp in Breakpoint.bplist[filename, lineno][:]:
  252.             bp.deleteMe()
  253.         if not Breakpoint.bplist.has_key((filename, lineno)):
  254.             self.breaks[filename].remove(lineno)
  255.         if not self.breaks[filename]:
  256.             del self.breaks[filename]
  257.  
  258.     def clear_bpbynumber(self, arg):
  259.         try:
  260.             number = int(arg)
  261.         except:
  262.             return 'Non-numeric breakpoint number (%s)' % arg
  263.         try:
  264.             bp = Breakpoint.bpbynumber[number]
  265.         except IndexError:
  266.             return 'Breakpoint number (%d) out of range' % number
  267.         if not bp:
  268.             return 'Breakpoint (%d) already deleted' % number
  269.         self.clear_break(bp.file, bp.line)
  270.  
  271.     def clear_all_file_breaks(self, filename):
  272.         filename = self.canonic(filename)
  273.         if not filename in self.breaks:
  274.             return 'There are no breakpoints in %s' % filename
  275.         for line in self.breaks[filename]:
  276.             blist = Breakpoint.bplist[filename, line]
  277.             for bp in blist:
  278.                 bp.deleteMe()
  279.         del self.breaks[filename]
  280.  
  281.     def clear_all_breaks(self):
  282.         if not self.breaks:
  283.             return 'There are no breakpoints'
  284.         for bp in Breakpoint.bpbynumber:
  285.             if bp:
  286.                 bp.deleteMe()
  287.         self.breaks = {}
  288.  
  289.     def get_break(self, filename, lineno):
  290.         filename = self.canonic(filename)
  291.         return filename in self.breaks and \
  292.             lineno in self.breaks[filename]
  293.  
  294.     def get_breaks(self, filename, lineno):
  295.         filename = self.canonic(filename)
  296.         return filename in self.breaks and \
  297.             lineno in self.breaks[filename] and \
  298.             Breakpoint.bplist[filename, lineno] or []
  299.  
  300.     def get_file_breaks(self, filename):
  301.         filename = self.canonic(filename)
  302.         if filename in self.breaks:
  303.             return self.breaks[filename]
  304.         else:
  305.             return []
  306.  
  307.     def get_all_breaks(self):
  308.         return self.breaks
  309.  
  310.     # Derived classes and clients can call the following method
  311.     # to get a data structure representing a stack trace.
  312.  
  313.     def get_stack(self, f, t):
  314.         stack = []
  315.         if t and t.tb_frame is f:
  316.             t = t.tb_next
  317.         while f is not None:
  318.             stack.append((f, f.f_lineno))
  319.             if f is self.botframe:
  320.                 break
  321.             f = f.f_back
  322.         stack.reverse()
  323.         i = max(0, len(stack) - 1)
  324.         while t is not None:
  325.             stack.append((t.tb_frame, t.tb_lineno))
  326.             t = t.tb_next
  327.         if f is None:
  328.             i = max(0, len(stack) - 1)
  329.         return stack, i
  330.  
  331.     #
  332.  
  333.     def format_stack_entry(self, frame_lineno, lprefix=': '):
  334.         import linecache, repr
  335.         frame, lineno = frame_lineno
  336.         filename = self.canonic(frame.f_code.co_filename)
  337.         s = '%s(%r)' % (filename, lineno)
  338.         if frame.f_code.co_name:
  339.             s = s + frame.f_code.co_name
  340.         else:
  341.             s = s + "<lambda>"
  342.         if '__args__' in frame.f_locals:
  343.             args = frame.f_locals['__args__']
  344.         else:
  345.             args = None
  346.         if args:
  347.             s = s + repr.repr(args)
  348.         else:
  349.             s = s + '()'
  350.         if '__return__' in frame.f_locals:
  351.             rv = frame.f_locals['__return__']
  352.             s = s + '->'
  353.             s = s + repr.repr(rv)
  354.         line = linecache.getline(filename, lineno, frame.f_globals)
  355.         if line: s = s + lprefix + line.strip()
  356.         return s
  357.  
  358.     # The following two methods can be called by clients to use
  359.     # a debugger to debug a statement, given as a string.
  360.  
  361.     def run(self, cmd, globals=None, locals=None):
  362.         if globals is None:
  363.             import __main__
  364.             globals = __main__.__dict__
  365.         if locals is None:
  366.             locals = globals
  367.         self.reset()
  368.         sys.settrace(self.trace_dispatch)
  369.         if not isinstance(cmd, types.CodeType):
  370.             cmd = cmd+'\n'
  371.         try:
  372.             exec cmd in globals, locals
  373.         except BdbQuit:
  374.             pass
  375.         finally:
  376.             self.quitting = 1
  377.             sys.settrace(None)
  378.  
  379.     def runeval(self, expr, globals=None, locals=None):
  380.         if globals is None:
  381.             import __main__
  382.             globals = __main__.__dict__
  383.         if locals is None:
  384.             locals = globals
  385.         self.reset()
  386.         sys.settrace(self.trace_dispatch)
  387.         if not isinstance(expr, types.CodeType):
  388.             expr = expr+'\n'
  389.         try:
  390.             return eval(expr, globals, locals)
  391.         except BdbQuit:
  392.             pass
  393.         finally:
  394.             self.quitting = 1
  395.             sys.settrace(None)
  396.  
  397.     def runctx(self, cmd, globals, locals):
  398.         # B/W compatibility
  399.         self.run(cmd, globals, locals)
  400.  
  401.     # This method is more useful to debug a single function call.
  402.  
  403.     def runcall(self, func, *args, **kwds):
  404.         self.reset()
  405.         sys.settrace(self.trace_dispatch)
  406.         res = None
  407.         try:
  408.             res = func(*args, **kwds)
  409.         except BdbQuit:
  410.             pass
  411.         finally:
  412.             self.quitting = 1
  413.             sys.settrace(None)
  414.         return res
  415.  
  416.  
  417. def set_trace():
  418.     Bdb().set_trace()
  419.  
  420.  
  421. class Breakpoint:
  422.  
  423.     """Breakpoint class
  424.  
  425.     Implements temporary breakpoints, ignore counts, disabling and
  426.     (re)-enabling, and conditionals.
  427.  
  428.     Breakpoints are indexed by number through bpbynumber and by
  429.     the file,line tuple using bplist.  The former points to a
  430.     single instance of class Breakpoint.  The latter points to a
  431.     list of such instances since there may be more than one
  432.     breakpoint per line.
  433.  
  434.     """
  435.  
  436.     # XXX Keeping state in the class is a mistake -- this means
  437.     # you cannot have more than one active Bdb instance.
  438.  
  439.     next = 1        # Next bp to be assigned
  440.     bplist = {}     # indexed by (file, lineno) tuple
  441.     bpbynumber = [None] # Each entry is None or an instance of Bpt
  442.                 # index 0 is unused, except for marking an
  443.                 # effective break .... see effective()
  444.  
  445.     def __init__(self, file, line, temporary=0, cond=None, funcname=None):
  446.         self.funcname = funcname
  447.         # Needed if funcname is not None.
  448.         self.func_first_executable_line = None
  449.         self.file = file    # This better be in canonical form!
  450.         self.line = line
  451.         self.temporary = temporary
  452.         self.cond = cond
  453.         self.enabled = 1
  454.         self.ignore = 0
  455.         self.hits = 0
  456.         self.number = Breakpoint.next
  457.         Breakpoint.next = Breakpoint.next + 1
  458.         # Build the two lists
  459.         self.bpbynumber.append(self)
  460.         if self.bplist.has_key((file, line)):
  461.             self.bplist[file, line].append(self)
  462.         else:
  463.             self.bplist[file, line] = [self]
  464.  
  465.  
  466.     def deleteMe(self):
  467.         index = (self.file, self.line)
  468.         self.bpbynumber[self.number] = None   # No longer in list
  469.         self.bplist[index].remove(self)
  470.         if not self.bplist[index]:
  471.             # No more bp for this f:l combo
  472.             del self.bplist[index]
  473.  
  474.     def enable(self):
  475.         self.enabled = 1
  476.  
  477.     def disable(self):
  478.         self.enabled = 0
  479.  
  480.     def bpprint(self, out=None):
  481.         if out is None:
  482.             out = sys.stdout
  483.         if self.temporary:
  484.             disp = 'del  '
  485.         else:
  486.             disp = 'keep '
  487.         if self.enabled:
  488.             disp = disp + 'yes  '
  489.         else:
  490.             disp = disp + 'no   '
  491.         print >>out, '%-4dbreakpoint   %s at %s:%d' % (self.number, disp,
  492.                                                        self.file, self.line)
  493.         if self.cond:
  494.             print >>out, '\tstop only if %s' % (self.cond,)
  495.         if self.ignore:
  496.             print >>out, '\tignore next %d hits' % (self.ignore)
  497.         if (self.hits):
  498.             if (self.hits > 1): ss = 's'
  499.             else: ss = ''
  500.             print >>out, ('\tbreakpoint already hit %d time%s' %
  501.                           (self.hits, ss))
  502.  
  503. # -----------end of Breakpoint class----------
  504.  
  505. def checkfuncname(b, frame):
  506.     """Check whether we should break here because of `b.funcname`."""
  507.     if not b.funcname:
  508.         # Breakpoint was set via line number.
  509.         if b.line != frame.f_lineno:
  510.             # Breakpoint was set at a line with a def statement and the function
  511.             # defined is called: don't break.
  512.             return False
  513.         return True
  514.  
  515.     # Breakpoint set via function name.
  516.  
  517.     if frame.f_code.co_name != b.funcname:
  518.         # It's not a function call, but rather execution of def statement.
  519.         return False
  520.  
  521.     # We are in the right frame.
  522.     if not b.func_first_executable_line:
  523.         # The function is entered for the 1st time.
  524.         b.func_first_executable_line = frame.f_lineno
  525.  
  526.     if  b.func_first_executable_line != frame.f_lineno:
  527.         # But we are not at the first line number: don't break.
  528.         return False
  529.     return True
  530.  
  531. # Determines if there is an effective (active) breakpoint at this
  532. # line of code.  Returns breakpoint number or 0 if none
  533. def effective(file, line, frame):
  534.     """Determine which breakpoint for this file:line is to be acted upon.
  535.  
  536.     Called only if we know there is a bpt at this
  537.     location.  Returns breakpoint that was triggered and a flag
  538.     that indicates if it is ok to delete a temporary bp.
  539.  
  540.     """
  541.     possibles = Breakpoint.bplist[file,line]
  542.     for i in range(0, len(possibles)):
  543.         b = possibles[i]
  544.         if b.enabled == 0:
  545.             continue
  546.         if not checkfuncname(b, frame):
  547.             continue
  548.         # Count every hit when bp is enabled
  549.         b.hits = b.hits + 1
  550.         if not b.cond:
  551.             # If unconditional, and ignoring,
  552.             # go on to next, else break
  553.             if b.ignore > 0:
  554.                 b.ignore = b.ignore -1
  555.                 continue
  556.             else:
  557.                 # breakpoint and marker that's ok
  558.                 # to delete if temporary
  559.                 return (b,1)
  560.         else:
  561.             # Conditional bp.
  562.             # Ignore count applies only to those bpt hits where the
  563.             # condition evaluates to true.
  564.             try:
  565.                 val = eval(b.cond, frame.f_globals,
  566.                        frame.f_locals)
  567.                 if val:
  568.                     if b.ignore > 0:
  569.                         b.ignore = b.ignore -1
  570.                         # continue
  571.                     else:
  572.                         return (b,1)
  573.                 # else:
  574.                 #   continue
  575.             except:
  576.                 # if eval fails, most conservative
  577.                 # thing is to stop on breakpoint
  578.                 # regardless of ignore count.
  579.                 # Don't delete temporary,
  580.                 # as another hint to user.
  581.                 return (b,0)
  582.     return (None, None)
  583.  
  584. # -------------------- testing --------------------
  585.  
  586. class Tdb(Bdb):
  587.     def user_call(self, frame, args):
  588.         name = frame.f_code.co_name
  589.         if not name: name = '???'
  590.         print '+++ call', name, args
  591.     def user_line(self, frame):
  592.         import linecache
  593.         name = frame.f_code.co_name
  594.         if not name: name = '???'
  595.         fn = self.canonic(frame.f_code.co_filename)
  596.         line = linecache.getline(fn, frame.f_lineno, frame.f_globals)
  597.         print '+++', fn, frame.f_lineno, name, ':', line.strip()
  598.     def user_return(self, frame, retval):
  599.         print '+++ return', retval
  600.     def user_exception(self, frame, exc_stuff):
  601.         print '+++ exception', exc_stuff
  602.         self.set_continue()
  603.  
  604. def foo(n):
  605.     print 'foo(', n, ')'
  606.     x = bar(n*10)
  607.     print 'bar returned', x
  608.  
  609. def bar(a):
  610.     print 'bar(', a, ')'
  611.     return a/2
  612.  
  613. def test():
  614.     t = Tdb()
  615.     t.run('import bdb; bdb.foo(10)')
  616.  
  617. # end
  618.